package org.feng.support;

import cn.hutool.extra.spring.SpringUtil;
import org.apache.commons.lang3.StringUtils;
import org.feng.entity.SysScheduler;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;

/**
 * 执行工具类
 * @author : FengShuai
 * @since : 2024/6/27 9:24
 */
public class InvokeUtils {

    public static void invoke(SysScheduler scheduler) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String target = scheduler.getTarget();
        String beanName = getBeanName(target);
        String methodName = getMethodName(target);
        Object bean = SpringUtil.getBean(beanName);
        List<Object[]> methodParams = getMethodParams(target);
        if (methodParams != null && methodParams.size() > 0) {
            Method method = bean.getClass().getMethod(methodName, getMethodParamsType(methodParams));
            method.invoke(bean, getMethodParamsValue(methodParams));
        } else {
            Method method = bean.getClass().getMethod(methodName);
            method.invoke(bean);
        }
    }

    private static String getBeanName(String target) {
        String beanName = StringUtils.substringBefore(target, "(");
        return StringUtils.substringBeforeLast(beanName, ".");
    }

    private static String getMethodName(String target) {
        String beanName = StringUtils.substringBefore(target, "(");
        return StringUtils.substringAfter(beanName, ".");
    }

    private static List<Object[]> getMethodParams(String target) {
        String methodStr = StringUtils.substringBetween(target, "(", ")");
        if (StringUtils.isEmpty(methodStr)) {
            return null;
        }
        String[] methodParams = methodStr.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)");
        List<Object[]> clazz = new LinkedList<>();
        for (String methodParam : methodParams) {
            String str = StringUtils.trimToEmpty(methodParam);
            // String字符串类型，以@开头
            if (StringUtils.startsWithAny(str, "@")) {
                clazz.add(new Object[]{StringUtils.substring(str, 1, str.length()), String.class});
            }
            // boolean布尔类型，等于true或者false
            else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str)) {
                clazz.add(new Object[]{Boolean.valueOf(str), Boolean.class});
            }
            // long长整形，以L结尾
            else if (StringUtils.endsWith(str, "L")) {
                clazz.add(new Object[]{Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class});
            }
            // double浮点类型，以D结尾
            else if (StringUtils.endsWith(str, "D")) {
                clazz.add(new Object[]{Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class});
            }
            // 其他类型归类为整形
            else {
                clazz.add(new Object[]{Integer.valueOf(str), Integer.class});
            }
        }
        return clazz;
    }

    private static Class<?>[] getMethodParamsType(List<Object[]> methodParams) {
        Class<?>[] clazz = new Class<?>[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams) {
            clazz[index] = (Class<?>) os[1];
            index++;
        }
        return clazz;
    }

    private static Object[] getMethodParamsValue(List<Object[]> methodParams) {
        Object[] clazz = new Object[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams) {
            clazz[index] = os[0];
            index++;
        }
        return clazz;
    }
}
